#include "stack.h"

stack_t stack_init(int size){
    stack_t stack_;
    stack_.base = (stack_node_t*)calloc(size, sizeof(stack_node_t));
    stack_.base->next = nullptr;
    stack_.top = stack_.base;
    stack_.size = size;
    stack_.length = 0;
    return stack_;
}

stack_t stack(){
    return stack_init(STACK_INIT_SIZE);
}

int stack_len(stack_t s){
#if 0
    int count = 0;
    stack_node_t *node = s.top;
    while(node != nullptr){
        count++;
        node = node->next;
    }
    return count;
#else
    return s.length;
#endif
}

void debug_stack(stack_t s){
    // 自栈顶遍历
    stack_node_t *node = s.top->next;
    while(node != nullptr){
        debug_cstr(*node->data);
        node = node->next;
    }
}

void stack_push(stack_t *s, stack_elem_t *data){
    if(s->length >= s->size){
        s->base = (stack_node_t*)realloc(s->base, s->size + STACK_INCREMENT);
        s->size += STACK_INCREMENT;
    }

    s->top->data = data;
    stack_node_t *curr = s->top++;
    s->top->next = curr;
    s->length += 1;
}

stack_elem_t stack_pop(stack_t *s){
    assert(s->length);  // 空栈无法返回
    stack_elem_t *p_data = s->top->next->data;
#ifdef STACK_NODE_POP_REMAIN
    s->top = s->top->next;
#else
    stack_node_t *p_pop = s->top;
    s->top = s->top->next;
    p_pop = nullptr;
#endif
    s->length -= 1;
    return *p_data;
}

void stack_free(stack_t *s){
#ifdef STACK_NODE_POP_REMAIN
    while(s->top != s->base){
        stack_pop(s);
    }
#endif
    free(s->base);
    s->base = nullptr;
    s->top = nullptr;
    s->length = 0;
    s->size = 0;
}
